之所以說 Elixir 簡單,是因為比起物件導向,Elixir 只有 Function(函式) 沒有其他太抽象的隱藏概念,所有的組成都非常直覺。
定義 Module 使用 defmodule
關鍵字,並用 do
與 end
來將內容包起來。 Module 名稱使用 camel case.
defmodule MyModule do
end
所有的 function 都必須要在模組底下定義
defmodule MyModule do
def my_function do
"Hello World"
end
end
我們可以這樣呼叫
MyModule.my_function #=> "Hello World"
使用()
設定參數,並用 ,
分隔
def add_them(first, second) do
first + second
end
def add_them(first, second, third) do
first + second + third
end
在 Elixir 裡面同一個模組可以有相同名字的函式,在稱呼這個函式的時候我們會一起寫上他的變數數量(arity),上面兩個函式分別是 add_them/2
與 add_them/3
,另外相同名字與相同 arity 的函式也是允許的,執行順序由上至下,這個在下個章節會說明。
.ex
檔案在上一篇我們都是使用 iex 來執行 Elixir 程式碼,但是在這邊要編輯並執行長一點的程式碼段落會很不方便,
我們可以使用編輯器並存成 .ex
檔案,通常會依照模組的名稱命名,如剛剛的範例可以叫:my_module.ex
接著可以在終端機執行 elixir my_module.ex
來執行它,
另外,在目前的章節,使用 iex 讀入該 module,再來執行會比較方便,
可以使用 iex my_module.ex
來開啟 iex 並執行該檔案內的程式碼
或是進入 iex 之後 使用 c("my_module.ex") 來讀取並執行
寫一個匯率轉換小程式,他的執行結果如下
(這邊先不用考慮精準度與匯率,先寫個極簡單版本熟悉 Module 與 function 即可)
iex "ex_currency.ex"
ExCurrency.to_usd(300)
#=> 30
ExCurrency.to_jpy(300)
#=> 1200
# ex_currency.ex
defmodule ExCurrency do
def to_usd(twd) do
div(twd, 30)
end
def to_jpy(twd) do
twd * 4
end
end
有幾個情況可以省略 module
defmodule ExCurrency do
def to_jpy(twd) do
twd * 4
end
def twd_2000_to_jpy() do
to_jpy(2000) #=> 這邊前面可以省略 ExCurrency
end
end
is_atom(:hi) #=> true
Kernel 文件可以看所有的 Kernel 函式
拿剛剛的小測驗為例
使用 iex ex_currency.ex
進入 iex 後
再執行 import ExCurrency
我們就可以直接呼叫 to_jpy/1
function
使用 fn
, ->
與 end
定義匿名函式
to_jpy = fn twd -> twd * 4 end
多行的情況
to_jpy = fn twd ->
# 很多行的複雜運算
twd * 4
end
簡寫,省去變數名稱,在 &()
內由 &1
代表第一個變數,依此類推
to_jpy = &(&1 * 4)
直接執行匿名函式需要加一個 .
不過實際上比較少這樣執行
to_jpy.(300)
#=> 1200
通常會在 Enum.map/2
或 Enum.reduce/3
等高階函式使用
(高階函式:使用一個或多個函式當作變數的函式)
在 Functional programming 中,function 可以被當作變數傳遞,
常見的情形如 Enum.map/2
匿名函式的情況
Enum.map([1, 2, 3], fn x -> x + 1 end)
普通函式,則是加上 &
並使用 /
標記上 arity
Enum.map(["one", "two", "three"], &String.upcase/1)
#=> ["ONE", "TWO", "THREE"]
除了可以省略模組的 Kernel 外 (其實 +
, -
也是 Kernel 的函式)
我們寫應用的時候最常使用到的有下面幾個
List.first([1, 2, 3])
#=> 1
List.delete([:a, :b, :c], :d)
#=> [:a, :b, :c]
要注意的是,list 這個型別有 Enumerable protocol 所以可以使用 Enum 模組的函式
其實平常使用在 list 上的函式屬於 Enum 模組的情況還比較常見
Enum.count([1, 2, 3])
#=> 3
Enum.map([1, 2, 3], fn x -> x * 2 end)
#=> [2, 4, 6]
Enum.sort([3, 2, 1])
#=> [1, 2, 3]
在寫 Phoenix 應用的時候常常要處理 Map 與 Struct(之後介紹)
Map.get(%{name: "Jack", age: 3}, :name)
#=> "Jack"
Map.merge(%{a: 1, b: 2}, %{a: 3, d: 4})
#=> %{a: 3, b: 2, d: 4}
Map.keys(%{a: 1, b: 2})
[:a, :b]
收集了字串相關的方法,如
String.downcase("ABCD")
#=> "abcd"
String.replace("a,b,c", ",", "-")
#=> "a-b-c"